home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Freeware / Miro 1.0 / Miro_Installer.exe / Miro_Downloader.exe / dl_daemon / daemon.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2007-11-12  |  8.8 KB  |  268 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.5)
  3.  
  4. from dl_daemon import command
  5. import os
  6. import cPickle
  7. import socket
  8. import traceback
  9. from time import sleep
  10. from struct import pack, unpack, calcsize
  11. import tempfile
  12. import config
  13. import prefs
  14. import eventloop
  15. import util
  16. import logging
  17. from httpclient import ConnectionHandler
  18. SIZE_OF_INT = calcsize('I')
  19.  
  20. class DaemonError(Exception):
  21.     '''Exception while communicating to a daemon (either controller or
  22.     downloader).
  23.     '''
  24.     pass
  25.  
  26. firstDaemonLaunch = '1'
  27.  
  28. def launchDownloadDaemon(oldpid, port):
  29.     global firstDaemonLaunch
  30.     daemonEnv = {
  31.         'DEMOCRACY_DOWNLOADER_PORT': str(port),
  32.         'DEMOCRACY_DOWNLOADER_FIRST_LAUNCH': firstDaemonLaunch }
  33.     import app
  34.     delegate = app.delegate
  35.     delegate.launchDownloadDaemon(oldpid, daemonEnv)
  36.     firstDaemonLaunch = '0'
  37.  
  38.  
  39. def getDataFile():
  40.     
  41.     try:
  42.         uid = os.getuid()
  43.     except:
  44.         uid = os.environ['USERNAME']
  45.  
  46.     shortAppName = 'Miro'
  47.     return os.path.join(tempfile.gettempdir(), '%s_Download_Daemon_%s.txt' % (shortAppName, uid))
  48.  
  49. pidfile = None
  50.  
  51. def writePid(pid):
  52.     '''Write out our pid.
  53.  
  54.     This method locks the pid file until the downloader exits.  On windows
  55.     this is achieved by keeping the file open.  On Unix/OS X, we use the
  56.     fcntl.lockf() function.
  57.     '''
  58.     global pidfile
  59.     fd = os.open(getDataFile(), os.O_WRONLY | os.O_CREAT)
  60.     pidfile = os.fdopen(fd, 'w')
  61.     
  62.     try:
  63.         import fcntl
  64.     except:
  65.         pass
  66.  
  67.     fcntl.lockf(pidfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
  68.     pidfile.write('%s\n' % pid)
  69.     pidfile.flush()
  70.  
  71.  
  72. def readPid():
  73.     
  74.     try:
  75.         f = open(getDataFile(), 'r')
  76.     except IOError:
  77.         return None
  78.  
  79.     
  80.     try:
  81.         return int(f.readline())
  82.     except ValueError:
  83.         return None
  84.     finally:
  85.         f.close()
  86.  
  87.  
  88. lastDaemon = None
  89.  
  90. class Daemon(ConnectionHandler):
  91.     
  92.     def __init__(self):
  93.         global lastDaemon
  94.         ConnectionHandler.__init__(self)
  95.         lastDaemon = self
  96.         self.waitingCommands = { }
  97.         self.returnValues = { }
  98.         self.size = 0
  99.         self.states['ready'] = self.onSize
  100.         self.states['command'] = self.onCommand
  101.         self.queuedCommands = []
  102.         self.shutdown = False
  103.         self.stream.disableReadTimeout = True
  104.  
  105.     
  106.     def onError(self, error):
  107.         '''Call this when an error occurs.  It forces the
  108.         daemon to close its connection.
  109.         '''
  110.         logging.warning('socket error in daemon, closing my socket')
  111.         self.closeConnection()
  112.         raise error
  113.  
  114.     
  115.     def onConnection(self, socket):
  116.         self.changeState('ready')
  117.         for comm, callback in self.queuedCommands:
  118.             self.send(comm, callback)
  119.         
  120.         self.queuedCommands = []
  121.  
  122.     
  123.     def onSize(self):
  124.         if self.buffer.length >= SIZE_OF_INT:
  125.             (self.size,) = unpack('I', self.buffer.read(SIZE_OF_INT))
  126.             self.changeState('command')
  127.         
  128.  
  129.     
  130.     def onCommand(self):
  131.         if self.buffer.length >= self.size:
  132.             
  133.             try:
  134.                 comm = cPickle.loads(self.buffer.read(self.size))
  135.             except:
  136.                 logging.exception('WARNING: error unpickling command.')
  137.  
  138.             self.processCommand(comm)
  139.             self.changeState('ready')
  140.         
  141.  
  142.     
  143.     def processCommand(self, comm):
  144.         util.timeTrapCall('Running: %s' % (comm,), self.runCommand, comm)
  145.  
  146.     
  147.     def runCommand(self, comm):
  148.         comm.setDaemon(self)
  149.         comm.action()
  150.  
  151.     
  152.     def send(self, comm, callback = None):
  153.         if self.state == 'initializing':
  154.             self.queuedCommands.append((comm, callback))
  155.         else:
  156.             raw = cPickle.dumps(comm, cPickle.HIGHEST_PROTOCOL)
  157.             self.sendData(pack('I', len(raw)) + raw, callback)
  158.  
  159.  
  160.  
  161. class DownloaderDaemon(Daemon):
  162.     
  163.     def __init__(self, port):
  164.         writePid(os.getpid())
  165.         Daemon.__init__(self)
  166.         self.openConnection('127.0.0.1', port, self.onConnection, self.onError)
  167.  
  168.     
  169.     def handleClose(self, type):
  170.         if self.shutdown:
  171.             return None
  172.         
  173.         self.shutdown = True
  174.         eventloop.quit()
  175.         logging.warning('downloader: connection closed -- quitting')
  176.         download = download
  177.         import dl_daemon
  178.         download.shutDown()
  179.         import threading
  180.         for thread in threading.enumerate():
  181.             if thread != threading.currentThread() and not thread.isDaemon():
  182.                 thread.join()
  183.                 continue
  184.         
  185.  
  186.  
  187.  
  188. class ControllerDaemon(Daemon):
  189.     
  190.     def __init__(self):
  191.         Daemon.__init__(self)
  192.         self.stream.acceptConnection('127.0.0.1', 0, self.onConnection, self.onError)
  193.         self.port = self.stream.port
  194.         launchDownloadDaemon(readPid(), self.port)
  195.         data = { }
  196.         remoteConfigItems = [
  197.             prefs.LIMIT_UPSTREAM,
  198.             prefs.UPSTREAM_LIMIT_IN_KBS,
  199.             prefs.BT_MIN_PORT,
  200.             prefs.BT_MAX_PORT,
  201.             prefs.MOVIES_DIRECTORY,
  202.             prefs.PRESERVE_DISK_SPACE,
  203.             prefs.PRESERVE_X_GB_FREE,
  204.             prefs.SUPPORT_DIRECTORY,
  205.             prefs.SHORT_APP_NAME,
  206.             prefs.LONG_APP_NAME,
  207.             prefs.APP_PLATFORM,
  208.             prefs.APP_VERSION,
  209.             prefs.APP_SERIAL,
  210.             prefs.APP_REVISION,
  211.             prefs.PUBLISHER,
  212.             prefs.PROJECT_URL,
  213.             prefs.DOWNLOADER_LOG_PATHNAME,
  214.             prefs.LOG_PATHNAME,
  215.             prefs.GETTEXT_PATHNAME]
  216.         for desc in remoteConfigItems:
  217.             data[desc.key] = config.get(desc)
  218.         
  219.         c = command.InitialConfigCommand(self, data)
  220.         c.send()
  221.         config.addChangeCallback(self.updateConfig)
  222.  
  223.     
  224.     def updateConfig(self, key, value):
  225.         if not self.shutdown:
  226.             c = command.UpdateConfigCommand(self, key, value)
  227.             c.send()
  228.         
  229.  
  230.     
  231.     def handleClose(self, type):
  232.         if not self.shutdown:
  233.             logging.warning('Downloader Daemon died')
  234.             self.shutdown = True
  235.             config.removeChangeCallback(self.updateConfig)
  236.         
  237.  
  238.     
  239.     def shutdown_timeout_cb(self):
  240.         logging.warning('killing download daemon')
  241.         import app
  242.         delegate = app.delegate
  243.         delegate.killProcess(readPid())
  244.         self.shutdownResponse()
  245.  
  246.     
  247.     def shutdownResponse(self):
  248.         if self.shutdown_callback:
  249.             self.shutdown_callback()
  250.         
  251.         self.shutdown_timeout_dc.cancel()
  252.  
  253.     
  254.     def shutdownDownloaderDaemon(self, timeout = 5, callback = None):
  255.         """Send the downloader daemon the shutdown command.  If it doesn't
  256.         reply before timeout expires, kill it.  (The reply is not sent until
  257.         the downloader daemon has one remaining thread and that thread will
  258.         immediately exit).
  259.         """
  260.         self.shutdown_callback = callback
  261.         c = command.ShutDownCommand(self)
  262.         c.send()
  263.         self.shutdown = True
  264.         config.removeChangeCallback(self.updateConfig)
  265.         self.shutdown_timeout_dc = eventloop.addTimeout(timeout, self.shutdown_timeout_cb, 'Waiting for dl_daemon shutdown')
  266.  
  267.  
  268.